package com.fwtai.service.web;

import com.alibaba.fastjson2.JSONObject;
import com.fwtai.bean.PageFormData;
import com.fwtai.bean.UploadFile;
import com.fwtai.bean.UploadObject;
import com.fwtai.service.AsyncService;
import com.fwtai.tool.IdBuilder;
import com.fwtai.tool.ToolClient;
import com.fwtai.tool.ToolString;
import com.fwtai.web.MallGoodsDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 产品（商品）业务层
 * @作者 田应平
 * @版本 v1.0
 * @QQ号码 444141300
 * @Email service@fwtai.com
 * @创建日期 2023-10-31 15:22:53
 * @官网 <url>http://www.fwtai.com</url>
*/
@Service
public class MallGoodsService{

  @Value("${upload_dir_window}")
  private String dir_window;

  @Value("${upload_dir_linux}")
  private String dir_linux;

  private final AsyncService asyncService;

  private final MallGoodsDao mallGoodsDao;

  private final ThreadPoolTaskExecutor taskExecutor;

  public MallGoodsService(final MallGoodsDao mallGoodsDao,final ThreadPoolTaskExecutor taskExecutor,final AsyncService asyncService){
    this.mallGoodsDao = mallGoodsDao;
    this.taskExecutor = taskExecutor;
    this.asyncService = asyncService;
  }

  public String add(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_name = "name";
      final String p_category = "category";
      final String p_thumbnail = "thumbnail";
      final String p_cover = "cover";
      final String p_tips = "tips";
      final String p_details = "details";
      final String p_sort = "sort";
      final String p_size_name = "size_name";
      final String p_size_price = "size_price";
      final String p_size_inventory = "size_inventory";
      final String validate = ToolClient.validateField(formData,p_name,p_category,p_details,p_size_name,p_size_price,p_size_inventory);
      if(validate != null) return validate;
      final String len_name = formData.getString(p_name);
      if(len_name != null && len_name.length() > 128){
        return ToolClient.createJsonFail("产品名称字数太多");
      }
      final String len_category = formData.getString(p_category);
      if(len_category != null && len_category.length() > 19){
        return ToolClient.createJsonFail("产品分类字数太多");
      }
      final String len_tips = formData.getString(p_tips);
      if(len_tips != null && len_tips.length() > 512){
        return ToolClient.createJsonFail("提示字数太多");
      }
      final String len_details = formData.getString(p_details);
      if(len_details != null && len_details.length() > 921600000){
        return ToolClient.createJsonFail("产品描述字数太多");
      }
      final String size_name = formData.getString(p_size_name);
      if(size_name.length() > 64){
        return ToolClient.createJsonFail("规格名称字数太多");
      }
      final String len_price = formData.getString(p_size_price);
      if(len_price.length() > 15){
        return ToolClient.createJsonFail("产品价格字数太多");
      }
      final BigDecimal v_price = formData.getBigDecimal(p_size_price);
      formData.put(p_size_price,v_price);
      final String len_inventory = formData.getString(p_size_inventory);
      if(len_inventory != null && len_inventory.length() > 10){
        return ToolClient.createJsonFail("库存字数太多");
      }
      final Integer v_inventory = formData.getInteger(p_size_inventory);
      if(v_inventory != null){
        formData.put(p_size_inventory,v_inventory);
      }
      final String len_sort = formData.getString(p_sort);
      if(len_sort != null && len_sort.length() > 10){
        return ToolClient.createJsonFail("排序号字数太多");
      }
      final Long v_category = formData.getLong(p_category);
      if(v_category == null){
        return ToolClient.createJsonFail("产品分类不是有效的数据格式");
      }else{
        formData.put(p_category,v_category);
      }
      final Integer v_sort = formData.getInteger(p_sort);
      if(v_sort != null){
        formData.put(p_sort,v_sort);
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/goods",false,6,2,new String[]{p_cover,p_thumbnail});
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      formData.remove(p_thumbnail);
      formData.remove(p_cover);
      final boolean b = listFiles == null || listFiles.isEmpty();
      if(b) return ToolClient.createJsonFail("请选择上传文件");
      final ArrayList<String> lists = new ArrayList<>(1);
      lists.add(p_thumbnail);
      asyncService.handlerFile(formData,listFiles,lists);//适用于json类型且是单文件字段
      final ArrayList<String> listName = new ArrayList<>(1);
      listFiles.forEach(uploadFile -> {
        listName.add(uploadFile.getName());
      });
      //list分组
      final Map<String,List<String>> collects = listName.stream().collect(Collectors.groupingBy(itemValue -> {
        return itemValue.substring(0,itemValue.length() - 1);
      }));
      asyncService.handlerFile(formData,listFiles,collects,p_cover);//多文件上传,若有bug则换用下面注释的那个
      final HashMap<String,String> fields = new HashMap<>(1);
      fields.put("spec_img",p_thumbnail);
      final String compress = asyncService.compressPic(formData,listFiles,taskExecutor,4,fields);
      if(compress != null){
        return compress;
      }
      formData.put("kid",new IdBuilder().getId121L());
      formData.put("size_id",new IdBuilder().getId121L());
      return ToolClient.executeRows(mallGoodsDao.add(formData));
    },taskExecutor).join();
  }

  public String edit(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_kid = "kid";
      final String p_name = "name";
      final String p_category = "category";
      final String p_thumbnail = "thumbnail";
      final String p_cover = "cover";
      final String p_tips = "tips";
      final String p_details = "details";
      final String p_sort = "sort";
      final String validate = ToolClient.validateField(formData,p_kid,p_name,p_category,p_details);
      if(validate != null) return validate;
      final String len_name = formData.getString(p_name);
      if(len_name != null && len_name.length() > 128){
        return ToolClient.createJsonFail("产品名称字数太多");
      }
      final String len_category = formData.getString(p_category);
      if(len_category != null && len_category.length() > 19){
        return ToolClient.createJsonFail("产品分类字数太多");
      }
      final String len_tips = formData.getString(p_tips);
      if(len_tips != null && len_tips.length() > 512){
        return ToolClient.createJsonFail("提示字数太多");
      }
      final String len_details = formData.getString(p_details);
      if(len_details != null && len_details.length() > 921600000){
        return ToolClient.createJsonFail("产品描述字数太多");
      }
      final String len_sort = formData.getString(p_sort);
      if(len_sort != null && len_sort.length() > 10){
        return ToolClient.createJsonFail("排序号字数太多");
      }
      final Long v_category = formData.getLong(p_category);
      if(v_category == null){
        return ToolClient.createJsonFail("产品分类不是有效的数据格式");
      }else{
        formData.put(p_category,v_category);
      }
      if(len_sort != null){
        final Integer v_sort = formData.getInteger(p_sort);
        if(v_sort == null){
          return ToolClient.createJsonFail("排序号不是有效的数字");
        }else{
          formData.put(p_sort,v_sort);
        }
      }
      final long kid = formData.getLong(p_kid);
      final Long value = mallGoodsDao.queryExistById(kid);
      if(value == null){
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/goods",false,6,3,null);
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      final boolean b = listFiles != null && !listFiles.isEmpty();
      formData.remove(p_thumbnail);
      formData.remove(p_cover);
      final String[] listMulti = new String[]{p_cover};//多文件上传的字段集
      if(b){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add(p_thumbnail);
        asyncService.handlerFile(formData,listFiles,lists);//适用于json类型(单文件上传)
        final ArrayList<String> listName = new ArrayList<>(2);
        listFiles.forEach(uploadFile -> listName.add(uploadFile.getName()));
        //list分组,会含单文件字段,但不影响下列的操作
        final Map<String,List<String>> collects = listName.stream().collect(Collectors.groupingBy(itemValue -> itemValue.substring(0,itemValue.length() - 1)));
        asyncService.handlerFile(formData,listFiles,collects,listMulti);//适用于json类型(多文件上传)
        formData.put("collects_columns",collects);//获取已上传文件的字段
      }
      formData.put(p_kid,kid);
      final int rows = mallGoodsDao.edit(formData);
      return ToolClient.executeRows(rows);
    },taskExecutor).join();
  }

  public String queryById(final Long kid){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null){
        return ToolClient.jsonValidateField();
      }
      return ToolClient.queryJson(mallGoodsDao.queryById(kid));
    },taskExecutor).join();
  }

  //适用于详情里含有列表,即适用于一对多,可参考 jqdjk-backend/jqdjk-service/src/main/java/com/fwtai/service/api/ApiServiceService.java
  public String queryInfo(final Long kid){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null){
        return ToolClient.jsonValidateField();
      }
      return CompletableFuture.supplyAsync(()-> mallGoodsDao.queryById(kid),taskExecutor).thenApply((map) -> {
        if(map == null) return ToolClient.createJsonFail("数据不存在,刷新重试");
        /*asyncService.updateServiceBrowse(kid);//更新浏览量
        //此处是查询一对多
        final List<HashMap<String,Object>> list = CompletableFuture.supplyAsync(()-> goodsDao.queryList(kid),taskExecutor).join();
        if(list.size() > 0){
          map.put("list",list);
        }*/
        return ToolClient.queryJson(map);
      }).join();
    },taskExecutor).join();
  }

  public String delByKeys(final String ids){
    return CompletableFuture.supplyAsync(()->{
      if(ids == null || ids.length() == 0){
        return ToolClient.jsonValidateField();
      }
      final long[] list = ToolString.keysToArarry(ids);
      if(list == null){
        return ToolClient.createJsonFail("请选择要删除的数据");
      }
      final List<HashMap<String,String>> files = mallGoodsDao.queryFiles(list);
      if(files.isEmpty()){
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final int rows = mallGoodsDao.delByKeys(list);
      if(rows > 0){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add("thumbnail");
        for(int x = lists.size() - 1; x >= 0; x--){
          final String key = lists.get(x);
          for(int y = files.size() - 1; y >= 0; y--){
            final HashMap<String,String> map = files.get(y);
            for(final String k : map.keySet()){
              if(k.equals(key)){
                asyncService.delFileJsonObject(map.get(key));//视情况是否删除时连同删除文件
                break;
              }
            }
          }
        }
        final String[] listMulti = new String[]{"cover"};//多文件上传的字段集
        for(int x = listMulti.length - 1; x >= 0; x--){
          for(int y = files.size() - 1; y >= 0; y--){
            asyncService.delFileJsonObjects(files.get(y).get(listMulti[x]));//多文件上传,json里含json
          }
        }
      }
      return ToolClient.executeRows(rows,"操作成功","数据不存在,刷新重试");
    },taskExecutor).join();
  }

  public String editValid(final Long kid,final Integer enabled){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null || enabled == null){
        return ToolClient.jsonValidateField();
      }
      final Long value = mallGoodsDao.queryExistById(kid);
      if(value == null){
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final PageFormData formData = new PageFormData(2);
      formData.put("kid",kid);
      formData.put("enabled",enabled);
      return ToolClient.executeRows(mallGoodsDao.editValid(formData),"操作成功","操作失败,刷新重试");
    },taskExecutor).join();
  }

  public String getGoodsSpecList(final PageFormData formData){
    return CompletableFuture.supplyAsync(()->{
      try{
        if(ToolClient.dataTableMysql(formData,"goods_id") == null) return ToolClient.dataTableException("请求参数有误");
        final CompletableFuture<List<HashMap<String,Object>>> listData = CompletableFuture.supplyAsync(() -> mallGoodsDao.getGoodsSpecList(formData),taskExecutor);
        final CompletableFuture<Integer> listTotal = CompletableFuture.supplyAsync(() -> mallGoodsDao.getGoodsSpecTotal(formData),taskExecutor);
        return ToolClient.dataTableOK(listData.join(),listTotal.join());
      } catch (final Exception ignored){
        return ToolClient.dataTableException();
      }
    },taskExecutor).join();
  }

  public String listData(final PageFormData formData){
    return CompletableFuture.supplyAsync(()->{
      try{
        if(ToolClient.dataTableMysql(formData) == null) return ToolClient.jsonValidateField();
        final CompletableFuture<List<HashMap<String,Object>>> listData = CompletableFuture.supplyAsync(() -> mallGoodsDao.getListData(formData),taskExecutor);
        final CompletableFuture<Integer> listTotal = CompletableFuture.supplyAsync(() -> mallGoodsDao.getListTotal(formData),taskExecutor);
        return ToolClient.dataTableOK(listData.join(),listTotal.join());
      } catch (final Exception ignored){
        return ToolClient.dataTableException();
      }
    },taskExecutor).join();
  }

  //获取表goods的字段category的下拉框列动态值选项的数据
  public String getCategory(){
    return CompletableFuture.supplyAsync(()->ToolClient.queryJson(mallGoodsDao.getCategory()),taskExecutor).join();
  }

  public String querySpecInfo(final Long kid){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null){
        return ToolClient.jsonValidateField();
      }
      return ToolClient.queryJson(mallGoodsDao.querySpecInfo(kid));
    },taskExecutor).join();
  }

  public String addGoodSpec(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_goods_id = "goods_id";
      final String p_size_name = "size_name";
      final String p_size_price = "size_price";
      final String p_size_inventory = "size_inventory";
      final String p_market = "market";
      final String p_order_by = "order_by";
      final String p_spec_img = "spec_img";
      final String validate = ToolClient.validateField(formData,p_goods_id,p_size_name,p_size_price,p_size_inventory);
      if(validate != null) return validate;
      final String len_goods_id = formData.getString(p_goods_id);
      if(len_goods_id != null && len_goods_id.length() > 19){
        return ToolClient.createJsonFail("产品编号字数太多");
      }
      final String len_name = formData.getString(p_size_name);
      if(len_name != null && len_name.length() > 64){
        return ToolClient.createJsonFail("规格名称字数太多");
      }
      final String len_order_by = formData.getString(p_order_by);
      if(len_order_by != null && len_order_by.length() > 5){
        return ToolClient.createJsonFail("排序号字数太多");
      }
      final BigDecimal v_market = formData.getBigDecimal(p_market);
      if(v_market != null){
        formData.put(p_market,v_market);
      }
      final Integer size_inventory = formData.getInteger(p_size_inventory);
      if(size_inventory != null){
        formData.put(p_size_inventory,size_inventory);
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/goods_spec",false,1,1,new String[]{p_spec_img},".jpg",".jpeg",".png",".svg");
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      formData.remove(p_spec_img);
      listFiles.forEach(uploadFile -> {
        final JSONObject json = new JSONObject(4);
        json.put("fullPath",uploadFile.getFullPath());
        json.put("urlFile",uploadFile.getUrlFile());
        json.put("fileSize",uploadFile.getFileSize());
        json.put("originalName",uploadFile.getOriginalName());
        json.put("currentDir",uploadFile.getCurrentDir());
        formData.put(p_spec_img,json.toJSONString());
      });
      final String compress = asyncService.compressPic(formData,listFiles,taskExecutor,4,p_spec_img);
      if(compress != null){
        return compress;
      }
      formData.put("size_id",new IdBuilder().getId121L());//注意,此处是规格的kid
      formData.put("kid",formData.getLong(p_goods_id));//注意,此处是商品的id
      return ToolClient.executeRows(mallGoodsDao.addGoodSpec(formData));
    },taskExecutor).join();
  }

  public String editGoodSpec(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_kid = "kid";
      final String p_size_name = "size_name";
      final String p_size_price = "size_price";
      final String p_market = "market";
      final String p_spec_img = "spec_img";
      final String p_size_inventory = "size_inventory";
      final String p_order_by = "order_by";
      final String validate = ToolClient.validateField(formData,p_kid,p_size_name,p_size_price,p_order_by,p_size_inventory);
      if(validate != null) return validate;
      final String len_name = formData.getString(p_size_name);
      if(len_name != null && len_name.length() > 20){
        return ToolClient.createJsonFail("规格名称字数太多");
      }
      final String len_price = formData.getString(p_size_price);
      if(len_price != null && len_price.length() > 15){
        return ToolClient.createJsonFail("销售价格字数太多");
      }
      final String len_market = formData.getString(p_market);
      if(len_market != null && len_market.length() > 15){
        return ToolClient.createJsonFail("市场价格字数太多");
      }
      final String len_inventory = formData.getString(p_size_inventory);
      if(len_inventory != null && len_inventory.length() > 10){
        return ToolClient.createJsonFail("库存量字数太多");
      }
      final String len_order_by = formData.getString(p_order_by);
      if(len_order_by != null && len_order_by.length() > 5){
        return ToolClient.createJsonFail("排序号字数太多");
      }
      final BigDecimal v_price = formData.getBigDecimal(p_size_price);
      if(v_price == null){
        return ToolClient.createJsonFail("销售价格不是有效的数字");
      }else{
        formData.put(p_size_price,v_price);
      }
      final BigDecimal v_market = formData.getBigDecimal(p_market);
      if(v_market != null){
        formData.put(p_market,v_market);
      }
      if(len_inventory != null){
        final Integer v_inventory = formData.getInteger(p_size_inventory);
        if(v_inventory == null){
          return ToolClient.createJsonFail("库存量不是有效的数字");
        }else{
          formData.put(p_size_inventory,v_inventory);
        }
      }
      if(len_order_by != null){
        final Integer v_order_by = formData.getInteger(p_order_by);
        if(v_order_by == null){
          return ToolClient.createJsonFail("排序号不是有效的数字");
        }else{
          formData.put(p_order_by,v_order_by);
        }
      }
      final long kid = formData.getLong(p_kid);
      final HashMap<String,String> v = mallGoodsDao.queryExistSpecById(kid);
      if(v == null){
        return ToolClient.createJsonFail("数据不存在,刷新重试");
      }
      final String baseDir = ToolString.isLinuxOS() ? dir_linux : dir_window;
      final UploadObject uploadObject = ToolClient.uploadFile(request,baseDir,"/goods_spec",false,1,1,null,".jpg",".jpeg",".png",".svg");
      final String errorMsg = uploadObject.getErrorMsg();
      if(errorMsg != null) return ToolClient.createJsonFail(errorMsg);
      final ArrayList<UploadFile> listFiles = uploadObject.getListFiles();
      final boolean b = listFiles != null && !listFiles.isEmpty();
      formData.remove(p_spec_img);
      if(b){
        final ArrayList<String> lists = new ArrayList<>(1);
        lists.add(p_spec_img);
        asyncService.handlerFile(formData,listFiles,lists);
      }
      if(formData.containsKey(p_spec_img)){
        final String compress = asyncService.compressPic(formData,listFiles,taskExecutor,4,p_spec_img);
        if(compress != null){
          return compress;
        }
      }
      formData.put(p_kid,kid);
      return ToolClient.executeRows(mallGoodsDao.editGoodSpec(formData));
    },taskExecutor).join();
  }

  public String editSpecStatus(final Long kid,final Integer enabled,final Long goodsId){
    return CompletableFuture.supplyAsync(()->{
      if(kid == null || enabled == null || goodsId == null){
        return ToolClient.jsonValidateField();
      }
      final PageFormData formData = new PageFormData(2);
      formData.put("kid",kid);
      formData.put("enabled",enabled);
      return ToolClient.executeRows(mallGoodsDao.editSpecStatus(formData));
    },taskExecutor).join();
  }
}